# uncompyle6 version 3.2.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: site-packages\PyInstaller\depend\dylib.py
"""
Manipulating with dynamic libraries.
"""
import os.path
from PyInstaller.utils.win32 import winutils

__all__ = ["exclude_list", "include_list", "include_library"]
import os, re
from PyInstaller.compat import is_win, is_unix, is_aix, is_darwin
import PyInstaller.log as logging

logger = logging.getLogger(__name__)
_BOOTLOADER_FNAMES = set(["run", "run_d", "runw", "runw_d"])
_excludes = set(
    [
        "advapi32\\.dll",
        "ws2_32\\.dll",
        "gdi32\\.dll",
        "oleaut32\\.dll",
        "shell32\\.dll",
        "ole32\\.dll",
        "coredll\\.dll",
        "crypt32\\.dll",
        "kernel32",
        "kernel32\\.dll",
        "msvcrt\\.dll",
        "rpcrt4\\.dll",
        "user32\\.dll",
        "python\\%s\\%s",
    ]
)
_includes = set()
_win_includes = set(
    [
        "atl100\\.dll",
        "msvcr100\\.dll",
        "msvcp100\\.dll",
        "mfc100\\.dll",
        "mfc100u\\.dll",
        "mfcmifc80\\.dll",
        "mfcm100\\.dll",
        "mfcm100u\\.dll",
        "api-ms-win-core.*",
        "api-ms-win-crt.*",
        "ucrtbase\\.dll",
        "vcruntime140\\.dll",
        "py(?:thon(?:com(?:loader)?)?|wintypes)\\d+\\.dll",
    ]
)
_win_excludes = set([".*\\.so", ".*\\.dylib", "Microsoft\\.Windows\\.Common-Controls"])
_unix_excludes = set(
    [
        "libc\\.so(\\..*)?",
        "libdl\\.so(\\..*)?",
        "libm\\.so(\\..*)?",
        "libpthread\\.so(\\..*)?",
        "librt\\.so(\\..*)?",
        "libthread_db\\.so(\\..*)?",
        "ld-linux\\.so(\\..*)?",
        "libBrokenLocale\\.so(\\..*)?",
        "libanl\\.so(\\..*)?",
        "libcidn\\.so(\\..*)?",
        "libcrypt\\.so(\\..*)?",
        "libnsl\\.so(\\..*)?",
        "libnss_compat.*\\.so(\\..*)?",
        "libnss_dns.*\\.so(\\..*)?",
        "libnss_files.*\\.so(\\..*)?",
        "libnss_hesiod.*\\.so(\\..*)?",
        "libnss_nis.*\\.so(\\..*)?",
        "libnss_nisplus.*\\.so(\\..*)?",
        "libresolv\\.so(\\..*)?",
        "libutil\\.so(\\..*)?",
        "libGL\\..*",
        "libxcb\\.so(\\..*)?",
        "libxcb-dri.*\\.so(\\..*)?",
    ]
)
_aix_excludes = set(
    [
        "libbz2\\.a",
        "libc\\.a",
        "libC\\.a",
        "libcrypt\\.a",
        "libdl\\.a",
        "libintl\\.a",
        "libpthreads\\.a",
        "librt\\\\.a",
        "librtl\\.a",
        "libz\\.a",
    ]
)
if is_win:
    _includes |= _win_includes
    _excludes |= _win_excludes
else:
    if is_aix:
        _excludes |= _aix_excludes
    else:
        if is_unix:
            _excludes |= _unix_excludes

    class ExcludeList(object):
        def __init__(self):
            self.regex = re.compile(("|").join(_excludes), re.I)

        def search(self, libname):
            if _excludes:
                return self.regex.match(os.path.basename(libname))
            else:
                return False

    class IncludeList(object):
        def __init__(self):
            self.regex = re.compile(("|").join(_includes), re.I)

        def search(self, libname):
            if _includes:
                return self.regex.match(os.path.basename(libname))
            else:
                return False

    exclude_list = ExcludeList()
    include_list = IncludeList()
    if is_darwin:
        from macholib import util

        class MacExcludeList(object):
            def __init__(self, global_exclude_list):
                self._exclude_list = global_exclude_list

            def search(self, libname):
                result = self._exclude_list.search(libname)
                if result:
                    return result
                else:
                    return util.in_system_path(libname)

        exclude_list = MacExcludeList(exclude_list)
    else:
        if is_win:

            class WinExcludeList(object):
                def __init__(self, global_exclude_list):
                    self._exclude_list = global_exclude_list
                    self._windows_dir = os.path.normpath(
                        winutils.get_windows_dir().lower()
                    )

                def search(self, libname):
                    libname = libname.lower()
                    result = self._exclude_list.search(libname)
                    if result:
                        return result
                    else:
                        fn = os.path.normpath(os.path.realpath(libname).lower())
                        return fn.startswith(self._windows_dir)

            exclude_list = WinExcludeList(exclude_list)

    def include_library(libname):
        """
        Check if a dynamic library should be included with application or not.
        """
        if exclude_list:
            if exclude_list.search(libname):
                if not include_list.search(libname):
                    return False
                return True
            else:
                return True

    def mac_set_relative_dylib_deps(libname, distname):
        """
        On Mac OS X set relative paths to dynamic library dependencies
        of `libname`.
        
        Relative paths allow to avoid using environment variable DYLD_LIBRARY_PATH.
        There are known some issues with DYLD_LIBRARY_PATH. Relative paths is
        more flexible mechanism.
        
        Current location of dependend libraries is derived from the location
        of the library path (paths start with '@loader_path').
        
        'distname'  path of the library relative to dist directory of frozen
                    executable. We need this to determine the level of directory
                    level for @loader_path of binaries not found in dist directory.
        
                    E.g. qt4 plugins are not in the same directory as Qt*.dylib
                    files. Without using '@loader_path/../..' for qt plugins
                    Mac OS X would not be able to resolve shared library
                    dependencies and qt plugins will not be loaded.
        """
        from macholib import util
        from macholib.MachO import MachO

        if os.path.basename(libname) in _BOOTLOADER_FNAMES:
            return
        parent_dir = ""
        if os.path.dirname(distname):
            parent_level = len(os.path.dirname(distname).split(os.sep))
            parent_dir = parent_level * (os.pardir + os.sep)

        def match_func(pth):
            """
            For system libraries is still used absolute path. It is unchanged.
            """
            if not util.in_system_path(pth):
                return os.path.join("@loader_path", parent_dir, os.path.basename(pth))

        dll = MachO(libname)
        dll.rewriteLoadCommands(match_func)
        try:
            f = open(dll.filename, "rb+")
            for header in dll.headers:
                f.seek(0)
                dll.write(f)

            f.seek(0, 2)
            f.flush()
            f.close()
        except Exception:
            pass
